#ifndef _WX_XMLRES_H_
#define _WX_XMLRES_H_

#include "wx/defs.h"
#include "wx/string.h"
#include "wx/dynarray.h"
#include "wx/datetime.h"
#include "wx/list.h"
#include "wx/gdicmn.h"
#include "wx/filesys.h"
#include "wx/bitmap.h"
#include "wx/icon.h"
#include "wx/artprov.h"
#include "wx/colour.h"
#include "wx/animate.h"
#include "wx/xml/xml.h"

class wxMenu;
class wxMenuBar;
class wxDialog;
class wxPanel;
class wxWindow;
class wxFrame;
class wxToolBar;

class wxXmlResourceHandler;
class wxXmlSubclassFactory;
class wxXmlSubclassFactoriesList;
class wxXmlResourceModule;

class wxXmlResourceDataRecord {
  public:
    wxXmlResourceDataRecord() : Doc( NULL ) {
      Time = wxDateTime::Now();
    }
    ~wxXmlResourceDataRecord() {delete Doc;}
    wxString File;
    wxXmlDocument *Doc;
    wxDateTime Time;
};

WX_DECLARE_USER_EXPORTED_OBJARRAY( wxXmlResourceDataRecord, wxXmlResourceDataRecords );

enum wxXmlResourceFlags {
  wxXRC_USE_LOCALE     = 1,
  wxXRC_NO_SUBCLASSING = 2,
  wxXRC_NO_RELOADING   = 4
};

class wxXmlResource : public wxObject {
  public:
    wxXmlResource( int flags = wxXRC_USE_LOCALE, const wxString& domain = wxEmptyString );
    wxXmlResource( const wxString& filemask, int flags = wxXRC_USE_LOCALE, const wxString& domain = wxEmptyString );
    virtual ~wxXmlResource();
    bool Load( const wxString& filemask );
    bool Unload( const wxString& filename );
    void InitAllHandlers();
    void AddHandler( wxXmlResourceHandler *handler );
    void InsertHandler( wxXmlResourceHandler *handler );
    void ClearHandlers();
    static void AddSubclassFactory( wxXmlSubclassFactory *factory );
    wxMenu *LoadMenu( const wxString& name );
    wxMenuBar *LoadMenuBar( wxWindow *parent, const wxString& name );
    wxMenuBar *LoadMenuBar( const wxString& name ) { return LoadMenuBar( NULL, name ); }
    wxToolBar *LoadToolBar( wxWindow *parent, const wxString& name );
    wxDialog *LoadDialog( wxWindow *parent, const wxString& name );
    bool LoadDialog( wxDialog *dlg, wxWindow *parent, const wxString& name );
    wxPanel *LoadPanel( wxWindow *parent, const wxString& name );
    bool LoadPanel( wxPanel *panel, wxWindow *parent, const wxString& name );
    wxFrame *LoadFrame( wxWindow* parent, const wxString& name );
    bool LoadFrame( wxFrame* frame, wxWindow *parent, const wxString& name );
    wxObject *LoadObject( wxWindow *parent, const wxString& name, const wxString& classname );
    bool LoadObject( wxObject *instance, wxWindow *parent, const wxString& name, const wxString& classname );
    wxBitmap LoadBitmap( const wxString& name );
    wxIcon LoadIcon( const wxString& name );
    bool AttachUnknownControl( const wxString& name, wxWindow *control, wxWindow *parent = NULL );
    static int GetXRCID( const wxChar *str_id, int value_if_not_found = wxID_NONE );
    static wxXmlResource *Get();
    static wxXmlResource *Set( wxXmlResource *res );
    int GetFlags() const { return m_flags; }
    void SetFlags( int flags ) { m_flags = flags; }
    wxChar* GetDomain() const { return m_domain; }
    void SetDomain( const wxChar* domain );
  protected:
    bool UpdateResources();
    wxXmlNode *FindResource( const wxString& name, const wxString& classname, bool recursive = false );
    wxXmlNode *DoFindResource( wxXmlNode *parent, const wxString& name, const wxString& classname, bool recursive );
    wxObject *CreateResFromNode( wxXmlNode *node, wxObject *parent, wxObject *instance = NULL, wxXmlResourceHandler *handlerToUse = NULL );
    static wxString ConvertFileNameToURL( const wxString& filename );
    static bool IsArchive( const wxString& filename );
  private:
    int m_flags;
    wxList m_handlers;
    wxXmlResourceDataRecords m_data;
    wxFileSystem m_curFileSystem;
    wxFileSystem& GetCurFileSystem() { return m_curFileSystem; }
    wxChar* m_domain;
    friend class wxXmlResourceHandler;
    friend class wxXmlResourceModule;
    static wxXmlSubclassFactoriesList *ms_subclassFactories;
    static wxXmlResource *ms_instance;
};

#define XRCID(str_id) \
  wxXmlResource::GetXRCID(wxT(str_id))

#define XRCCTRL(window, id, type) \
  (wxStaticCast((window).FindWindow(XRCID(id)), type))

class wxXmlResourceHandler : public wxObject {
    DECLARE_ABSTRACT_CLASS( wxXmlResourceHandler )
  public:
    wxXmlResourceHandler();
    virtual ~wxXmlResourceHandler() {}
    wxObject *CreateResource( wxXmlNode *node, wxObject *parent, wxObject *instance );
    virtual wxObject *DoCreateResource() = 0;
    virtual bool CanHandle( wxXmlNode *node ) = 0;
    void SetParentResource( wxXmlResource *res ) { m_resource = res; }
  protected:
    wxXmlResource *m_resource;
    wxArrayString m_styleNames;
    wxArrayInt m_styleValues;
    wxXmlNode *m_node;
    wxString m_class;
    wxObject *m_parent, *m_instance;
    wxWindow *m_parentAsWindow;
    bool IsOfClass( wxXmlNode *node, const wxString& classname );
    wxString GetNodeContent( wxXmlNode *node );
    bool HasParam( const wxString& param );
    wxXmlNode *GetParamNode( const wxString& param );
    wxString GetParamValue( const wxString& param );
    void AddStyle( const wxString& name, int value );
    void AddWindowStyles();
    int GetStyle( const wxString& param = wxT( "style" ), int defaults = 0 );
    wxString GetText( const wxString& param, bool translate = true );
    int GetID();
    wxString GetName();
    bool GetBool( const wxString& param, bool defaultv = false );
    long GetLong( const wxString& param, long defaultv = 0 );
    float GetFloat( const wxString& param, float defaultv = 0 );
    wxColour GetColour( const wxString& param, const wxColour& defaultv = wxNullColour );
    wxSize GetSize( const wxString& param = wxT( "size" ), wxWindow *windowToUse = NULL );
    wxPoint GetPosition( const wxString& param = wxT( "pos" ) );
    wxCoord GetDimension( const wxString& param, wxCoord defaultv = 0, wxWindow *windowToUse = NULL );
    wxBitmap GetBitmap( const wxString& param = wxT( "bitmap" ), const wxArtClient& defaultArtClient = wxART_OTHER,
                        wxSize size = wxDefaultSize );
    wxIcon GetIcon( const wxString& param = wxT( "icon" ), const wxArtClient& defaultArtClient = wxART_OTHER,
                    wxSize size = wxDefaultSize );
    wxAnimation GetAnimation( const wxString& param = wxT( "animation" ) );
    wxFont GetFont( const wxString& param = wxT( "font" ) );
    void SetupWindow( wxWindow *wnd );
    void CreateChildren( wxObject *parent, bool this_hnd_only = false );
    void CreateChildrenPrivately( wxObject *parent, wxXmlNode *rootnode = NULL );
    wxObject *CreateResFromNode( wxXmlNode *node, wxObject *parent, wxObject *instance = NULL ) {
      return m_resource->CreateResFromNode( node, parent, instance );
    }
    wxFileSystem& GetCurFileSystem() { return m_resource->GetCurFileSystem(); }
};

#define XRC_ADD_STYLE(style) AddStyle(wxT(#style), style)

#define XRC_MAKE_INSTANCE(variable, classname) \
  classname *variable = NULL; \
  if (m_instance) \
    variable = wxStaticCast(m_instance, classname); \
  if (!variable) \
    variable = new classname;

void wxXmlInitResourceModule();

class wxXmlSubclassFactory {
  public:
    virtual wxObject *Create( const wxString& className ) = 0;
    virtual ~wxXmlSubclassFactory() {}
};

#endif
